#include "simulatedkeyboardcontrol.h"

#ifdef Q_OS_WIN
#include <windows.h>
#include <winuser.h> // 使用INPUT等结构体时
#include <atlconv.h> // 字符串转换
#include <ntddkbd.h>
#include <QDebug>

SimulatedKeyboardControl::SimulatedKeyboardControl() {}

void SimulatedKeyboardControl::sendKeyDown(quint8 key, bool useScanCode)
{
    // if (isExtendedKey(key)) {
    //     sendKeyUpEXTENDEDKEY(key);
    // } else {
    // 松开按键
    INPUT keyUpInput;
    ZeroMemory(&keyUpInput, sizeof(keyUpInput));
    keyUpInput.type = INPUT_KEYBOARD;
    keyUpInput.ki.wVk = key;
    if(useScanCode)
        keyUpInput.ki.wScan =  MapVirtualKey(key, MAPVK_VK_TO_VSC) ; // 扫描码 要管理员扫描码才有用
    keyUpInput.ki.dwFlags = 0;
    keyUpInput.ki.time = 0;
    keyUpInput.ki.dwExtraInfo = 0;
    // SendInput模拟按键松开
    if (SendInput(1, &keyUpInput, sizeof(INPUT)) != 1) {
        qCritical() << "无法通过SendInput模拟按键输入：" << HRESULT_FROM_WIN32(GetLastError());
    }
    // }
}

void SimulatedKeyboardControl::sendKeyUp(quint8 key, bool useScanCode)
{
    // if (isExtendedKey(key)) {
    //     sendKeyUpEXTENDEDKEY(key);
    // } else {
        // 松开按键
        INPUT keyUpInput;
        ZeroMemory(&keyUpInput, sizeof(keyUpInput));
        keyUpInput.type = INPUT_KEYBOARD;
        keyUpInput.ki.wVk = key;
        if(useScanCode)
            keyUpInput.ki.wScan =  MapVirtualKey(key, MAPVK_VK_TO_VSC) ; // 扫描码 要管理员扫描码才有用
        keyUpInput.ki.dwFlags = KEYEVENTF_KEYUP;
        keyUpInput.ki.time = 0;
        keyUpInput.ki.dwExtraInfo = 0;
        // SendInput模拟按键松开
        if (SendInput(1, &keyUpInput, sizeof(INPUT)) != 1) {
            qCritical() << "无法通过SendInput模拟按键输入：" << HRESULT_FROM_WIN32(GetLastError());
        }
        // }
}

void SimulatedKeyboardControl::sendKey(quint8 key, bool useScanCode,qint32 delay)
{
    sendKeyDown(key, useScanCode);
    // usleep(60*1000);
    // 等待60ms
    if(delay<0){
        Sleep(60);
    } else {
        Sleep(delay);
    }
    sendKeyUp(key,useScanCode);
}




#elif defined(Q_OS_MAC)
// 头文件
#include <CoreGraphics/CoreGraphics.h>


bool SimulatedKeyboardControl::isInit = false;
CGEventSourceRef SimulatedKeyboardControl::hidEventSource = NULL;
bool SimulatedKeyboardControl::shiftEventFlagCount = false;
bool SimulatedKeyboardControl::ctrlEventFlagCount = false;
bool SimulatedKeyboardControl::commandEventFlagCount = false;
bool SimulatedKeyboardControl::altEventFlagCount = false;

bool SimulatedKeyboardControl::tryToCreateHidEventSource()
{
    if (!isInit) {
        isInit = true;
        // 四个修饰键
        shiftEventFlagCount = false;
        ctrlEventFlagCount = false;
        commandEventFlagCount = false;
        altEventFlagCount = false;

        // kCGEventSourceStatePrivate：
        // 代表专门的应用，如远程控制程序可以生成和跟踪事件源状态独立于其他进程。
        // kCGEventSourceStateCombinedSessionState：
        // 该状态表反映了所有事件源的组合状态发布到当前用户的登录会话。
        // 如果您的程序发布的事件在一个登录会话，您应该使用这个源状态当你创建一个事件源。
        // kCGEventSourceStateHIDSystemState：
        // 该状态表反映了组合硬件输入源从 HID 系统硬件层面发送的事件源生成的事件。
        // 就是外接键盘或者 macbook 本机键盘以及一些系统定义的按键点击事件。
        hidEventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
    }

    return hidEventSource;
}

/**
 * @brief 发送键盘事件
 * @param 按键对应键值
 * @param 按键是否被按下
 */
bool SimulatedKeyboardControl::postKeyboardEvent(CGKeyCode virtualKey,
                       bool keyDown)
{
    if (!SimulatedKeyboardControl::tryToCreateHidEventSource()) {
        return false;
    }

    CGEventFlags flags = 0;
    if (SimulatedKeyboardControl::shiftEventFlagCount > 0) {
        flags |= kCGEventFlagMaskShift;
    }
    if (SimulatedKeyboardControl::ctrlEventFlagCount > 0) {
        flags |= kCGEventFlagMaskControl;
    }
    if (SimulatedKeyboardControl::commandEventFlagCount > 0) {
        flags |= kCGEventFlagMaskCommand;
    }
    if (SimulatedKeyboardControl::altEventFlagCount > 0) {
        flags |= kCGEventFlagMaskAlternate;
    }
    CGEventRef event = CGEventCreateKeyboardEvent(SimulatedKeyboardControl::hidEventSource, virtualKey, keyDown);
    CGEventSetFlags(event, flags);
    CGEventPost(kCGHIDEventTap, event);
    CFRelease(event);

    return true;
}


void SimulatedKeyboardControl::sendKeyDown(quint16 key)
{
   {
        // 更新 flags
        switch (value) {
        case 56: // L-Shift
        case 60: // R-Shift
            SimulatedKeyboardControl::shiftEventFlagCount = true;
            break;
        case 55: // L-Command
        case 54: // R-Command
            SimulatedKeyboardControl::commandEventFlagCount = true;
            break;
        case 58: // L-Alt
        case 61: // R-Alt
            SimulatedKeyboardControl::altEventFlagCount = true;
            break;
        case 59: // L-Ctrl
        case 62: // R-Ctrl
            SimulatedKeyboardControl::ctrlEventFlagCount = true;
            break;
        default:
            break;
        }
    }
   // 按下按键
    if (postKeyboardEvent(value, true)){
    }
    else {
        // 如果按下修饰键失败， 要把设置的修饰键复位
        {
            // 更新 flags
            switch (value) {
            case 56: // L-Shift
            case 60: // R-Shift
                SimulatedKeyboardControl::shiftEventFlagCount = false;
                break;
            case 55: // L-Command
            case 54: // R-Command
                SimulatedKeyboardControl::commandEventFlagCount = false;
                break;
            case 58: // L-Alt
            case 61: // R-Alt
                SimulatedKeyboardControl::altEventFlagCount = false;
                break;
            case 59: // L-Ctrl
            case 62: // R-Ctrl
                SimulatedKeyboardControl::ctrlEventFlagCount = false;
                break;
            default:
                break;
            }
        }

        qCritical() << __FUNCTION__ << "sendKeyDown fail";
    }
}

void SimulatedKeyboardControl::sendKeyUp(quint16 key)
{
    {
        // 更新 flags
        switch (value) {
        case 56: // L-Shift
        case 60: // R-Shift
            SimulatedKeyboardControl::shiftEventFlagCount = false;
            break;
        case 55: // L-Command
        case 54: // R-Command
            SimulatedKeyboardControl::commandEventFlagCount = false;
            break;
        case 58: // L-Alt
        case 61: // R-Alt
            SimulatedKeyboardControl::altEventFlagCount = false;
            break;
        case 59: // L-Ctrl
        case 62: // R-Ctrl
            SimulatedKeyboardControl::ctrlEventFlagCount = false;
            break;
        default:
            break;
        }
    }

    // 释放按键
     if (postKeyboardEvent(value, false)){
    } else {
         // 如果按下修饰键失败， 要把设置的修饰键复位
         {
             // 更新 flags
             switch (value) {
             case 56: // L-Shift
             case 60: // R-Shift
                 SimulatedKeyboardControl::shiftEventFlagCount = true;
                 break;
             case 55: // L-Command
             case 54: // R-Command
                 SimulatedKeyboardControl::commandEventFlagCount = true;
                 break;
             case 58: // L-Alt
             case 61: // R-Alt
                 SimulatedKeyboardControl::altEventFlagCount = true;
                 break;
             case 59: // L-Ctrl
             case 62: // R-Ctrl
                 SimulatedKeyboardControl::ctrlEventFlagCount = true;
                 break;
             default:
                 break;
             }
         }
        qCritical() << __FUNCTION__ << "sendKeyUp fail";
    }
}

void SimulatedKeyboardControl::sendKey(quint16 key,qint32 delay)
{
    // 按下按键
    sendKeyDown(value);
    // 延迟

    if(delay<0){
        usleep(60000);
    } else {
        usleep(delay*1000);
    }

    // 释放按键
    sendKeyUp(value);
}





#endif
